#!/usr/bin/env python3
"""
简化版dashboard - 使用服务端渲染，避免复杂JavaScript
"""
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import threading
import subprocess
import socket
import ssl
from urllib.parse import urlparse, parse_qs, unquote
from pathlib import Path
import time
import html

class SimpleDashboardHandler(BaseHTTPRequestHandler):
    def __init__(self, proxy_instance, *args, **kwargs):
        self.proxy = proxy_instance
        super().__init__(*args, **kwargs)

    def do_GET(self):
        parsed_path = urlparse(self.path)
        path = parsed_path.path
        query_params = parse_qs(parsed_path.query)
        
        if path == '/':
            self.serve_main_page(query_params)
        elif path == '/copy':
            self.serve_copy_page(query_params)
        elif path == '/replay':
            self.serve_replay_page(query_params)
        elif path == '/network-test':
            self.serve_network_test_page()
        else:
            self.send_error(404)
    
    def do_POST(self):
        parsed_path = urlparse(self.path)
        path = parsed_path.path
        
        content_length = int(self.headers.get('Content-Length', 0))
        post_data = self.rfile.read(content_length).decode('utf-8')
        post_params = parse_qs(post_data)
        
        if path == '/replay_request':
            self.handle_replay_post(post_params)
        else:
            self.send_error(404)

    def serve_main_page(self, query_params):
        """主页面 - 显示请求列表"""
        show_idea_only = query_params.get('idea_only', [''])[0] == '1'
        url_filter = query_params.get('url_filter', [''])[0].strip()
        
        # 获取请求数据
        requests = self.proxy.requests_log[-100:] if self.proxy.requests_log else []
        
        # 过滤IDEA请求
        if show_idea_only:
            requests = [req for req in requests 
                       if req.get('headers', {}).get('User-Agent', '').lower().find('idea') >= 0]
        
        # URL模糊匹配过滤
        if url_filter:
            filtered_requests = []
            for req in requests:
                method_line = req.get('method_line', '')
                url = method_line.split(' ')[1] if len(method_line.split(' ')) > 1 else ''
                # 模糊匹配：URL包含过滤关键词（不区分大小写）
                if url_filter.lower() in url.lower():
                    filtered_requests.append(req)
            requests = filtered_requests
        
        # 统计数据
        total_requests = len(self.proxy.requests_log)
        idea_requests = sum(1 for req in self.proxy.requests_log 
                           if req.get('headers', {}).get('User-Agent', '').lower().find('idea') >= 0)
        websocket_requests = sum(1 for req in self.proxy.requests_log 
                               if self.is_websocket_request_from_log(req))
        active_websockets = len(getattr(self.proxy, 'websocket_connections', {}))
        
        # 构建HTML
        html_content = self.build_main_html(total_requests, idea_requests, websocket_requests, active_websockets, len(requests), show_idea_only, url_filter, requests)
        
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(html_content.encode('utf-8'))

    def is_websocket_request_from_log(self, req):
        """Check if logged request was a WebSocket upgrade request"""
        headers = req.get('headers', {})
        return (
            headers.get('Upgrade', '').lower() == 'websocket' and
            'upgrade' in headers.get('Connection', '').lower() and
            'Sec-WebSocket-Key' in headers
        )
    
    def normalize_url_for_display(self, method, url):
        """Normalize URL for consistent display (same logic as CURL generation)"""
        # 处理CONNECT方法 - 转换为普通的HTTPS请求URL
        if method.upper() == 'CONNECT':
            # CONNECT host:port -> https://host/
            if url.endswith(':443'):
                # HTTPS端口，构建HTTPS URL
                host = url[:-4]  # 移除':443'
                return f"https://{host}/"
            elif url.endswith(':80'):
                # HTTP端口，构建HTTP URL  
                host = url[:-3]  # 移除':80'
                return f"http://{host}/"
            else:
                # 其他端口，假设是HTTPS并保留端口
                if ':' in url:
                    return f"https://{url}/"
                else:
                    return f"https://{url}/"
        
        # 其他方法的URL保持不变
        return url
    
    def build_main_html(self, total_requests, idea_requests, websocket_requests, active_websockets, current_count, show_idea_only, url_filter, requests):
        """构建主页面HTML"""
        filter_button = ""
        if show_idea_only:
            filter_button = '<button class="btn" onclick="location.href=\'/\'">显示全部</button>'
        else:
            filter_button = '<button class="btn" onclick="location.href=\'/?idea_only=1\'">仅显示IDEA</button>'
        
        html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .header {{ background: #667eea; color: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .stats {{ display: flex; gap: 20px; margin-bottom: 20px; }}
        .stat {{ background: white; padding: 15px; border-radius: 8px; text-align: center; }}
        .stat-number {{ font-size: 24px; font-weight: bold; color: #667eea; }}
        .controls {{ background: white; padding: 15px; border-radius: 8px; margin-bottom: 20px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; }}
        .btn:hover {{ background: #5a67d8; }}
        .btn-small {{ padding: 4px 8px; font-size: 12px; margin: 2px; }}
        .btn-copy {{ background: #17a2b8; }}
        .btn-replay {{ background: #ffc107; color: #212529; }}
        .btn-detail {{ background: #28a745; }}
        table {{ width: 100%; background: white; border-collapse: collapse; border-radius: 8px; overflow: hidden; }}
        th, td {{ padding: 12px; text-align: left; border-bottom: 1px solid #eee; }}
        th {{ background: #f8f9fa; font-weight: bold; }}
        .idea-row {{ background: #fff3cd; }}
        .websocket-row {{ background: #d1ecf1; border-left: 4px solid #17a2b8; }}
        .time {{ width: 80px; }}
        .method {{ width: 60px; }}
        .actions {{ width: 180px; }}
        .url {{ max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }}
        .filter-group {{ display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }}
        .filter-input {{ padding: 8px 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; min-width: 200px; }}
        .filter-input:focus {{ outline: none; border-color: #667eea; box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.2); }}
        .clear-btn {{ background: #dc3545; }}
        .clear-btn:hover {{ background: #c82333; }}
    </style>
    <script>
        function applyUrlFilter() {{
            const filterValue = document.getElementById('urlFilter').value.trim();
            const currentUrl = new URL(window.location);
            
            if (filterValue) {{
                currentUrl.searchParams.set('url_filter', filterValue);
            }} else {{
                currentUrl.searchParams.delete('url_filter');
            }}
            
            window.location.href = currentUrl.toString();
        }}
        
        function clearUrlFilter() {{
            document.getElementById('urlFilter').value = '';
            const currentUrl = new URL(window.location);
            currentUrl.searchParams.delete('url_filter');
            window.location.href = currentUrl.toString();
        }}
        
        function handleFilterKeyPress(event) {{
            if (event.key === 'Enter') {{
                applyUrlFilter();
            }}
        }}
    </script>
</head>
<body>
    <div class="header">
        <h1>🔍 IDEA Proxy Monitor</h1>
        <p>实时监控 IntelliJ IDEA 网络请求</p>
    </div>
    
    <div class="stats">
        <div class="stat">
            <div class="stat-number">{total_requests}</div>
            <div>总请求数</div>
        </div>
        <div class="stat">
            <div class="stat-number">{idea_requests}</div>
            <div>IDEA请求数</div>
        </div>
        <div class="stat">
            <div class="stat-number">{websocket_requests}</div>
            <div>WebSocket请求</div>
        </div>
        <div class="stat">
            <div class="stat-number" style="color: {'#28a745' if active_websockets > 0 else '#6c757d'}">{active_websockets}</div>
            <div>活跃WebSocket</div>
        </div>
        <div class="stat">
            <div class="stat-number">{current_count}</div>
            <div>当前显示</div>
        </div>
    </div>
    
    {'<div style="background: #fff3cd; padding: 10px; border-radius: 4px; margin-bottom: 10px; border-left: 4px solid #856404;"><strong>🔍 过滤状态:</strong> 显示包含 "<strong>' + html.escape(url_filter) + '</strong>" 的URL</div>' if url_filter else ''}
    
    <div class="controls">
        <div class="filter-group">
            <button class="btn" onclick="location.reload()">🔄 刷新</button>
            {filter_button}
            <button class="btn" onclick="location.href='/network-test'">🌐 网络测试</button>
        </div>
        
        <div class="filter-group" style="margin-top: 10px;">
            <label for="urlFilter" style="font-weight: bold;">🔍 URL过滤:</label>
            <input type="text" 
                   id="urlFilter" 
                   class="filter-input" 
                   placeholder="输入URL关键词进行模糊匹配..."
                   value="{url_filter}"
                   onkeypress="handleFilterKeyPress(event)">
            <button class="btn" onclick="applyUrlFilter()">过滤</button>
            <button class="btn clear-btn" onclick="clearUrlFilter()">清除</button>
        </div>
    </div>
    
    <table>
        <thead>
            <tr>
                <th class="time">时间</th>
                <th class="method">方法</th>
                <th class="url">URL</th>
                <th>客户端</th>
                <th>User-Agent</th>
                <th class="actions">操作</th>
            </tr>
        </thead>
        <tbody>
"""
        
        if not requests:
            html_content += '<tr><td colspan="6" style="text-align: center; padding: 40px;">暂无请求数据</td></tr>'
        else:
            # 获取最近50个请求，但保持原始索引
            recent_requests = requests[-50:] if requests else []
            reversed_requests = list(reversed(recent_requests))
            
            for display_index, req in enumerate(reversed_requests):
                # 计算在原始50个请求中的正确索引
                original_index = len(recent_requests) - 1 - display_index
                
                timestamp = req.get('timestamp', '')
                try:
                    from datetime import datetime
                    time_str = datetime.fromisoformat(timestamp.replace('Z', '+00:00')).strftime('%H:%M:%S')
                except:
                    time_str = timestamp[:8] if len(timestamp) > 8 else timestamp
                
                method_line = req.get('method_line', '')
                method = method_line.split(' ')[0] if method_line else 'Unknown'
                raw_url = method_line.split(' ')[1] if len(method_line.split(' ')) > 1 else 'Unknown'
                
                # 应用与复制功能相同的URL转换逻辑
                url = self.normalize_url_for_display(method, raw_url)
                
                client = req.get('client_addr', 'Unknown')
                user_agent = req.get('headers', {}).get('User-Agent', 'Unknown')
                
                is_idea = user_agent.lower().find('idea') >= 0
                is_websocket = self.is_websocket_request_from_log(req)
                
                row_class = ''
                if is_websocket:
                    row_class = 'websocket-row'
                elif is_idea:
                    row_class = 'idea-row'
                
                # URL截断显示
                display_url = (url[:60] + '...') if len(url) > 60 else url
                
                # User-Agent截断显示
                display_ua = (user_agent[:40] + '...') if len(user_agent) > 40 else user_agent
                
                # Add WebSocket indicator
                method_display = method
                if is_websocket:
                    method_display = f"🔌 {method}"
                
                html_content += f'''
                <tr class="{row_class}">
                    <td class="time">{html.escape(time_str)}</td>
                    <td class="method">{html.escape(method_display)}</td>
                    <td class="url" title="{html.escape(url)}">{html.escape(display_url)}</td>
                    <td>{html.escape(client)}</td>
                    <td title="{html.escape(user_agent)}">{html.escape(display_ua)}</td>
                    <td class="actions">
                        <button class="btn btn-small btn-copy" onclick="location.href='/copy?id={original_index}'">📋 复制</button>
                        <button class="btn btn-small btn-replay" onclick="location.href='/replay?id={original_index}'">🔄 重放</button>
                    </td>
                </tr>
                '''
        
        html_content += """
        </tbody>
    </table>
    
    <div style="margin-top: 20px; text-align: center; color: #666;">
        <p>💡 点击"复制"获取请求内容，点击"重放"重新发送请求</p>
    </div>
</body>
</html>"""
        
        return html_content

    def build_curl_command(self, req):
        """构建CURL命令和原始请求"""
        raw_request = req.get('raw_request', '')
        method_line = req.get('method_line', '')
        headers = req.get('headers', {})
        body = req.get('body', '')
        
        # 首先显示完整的原始请求
        original_request_section = f"""# ===== 完整原始请求 =====
# 这是代理服务器监听到的完整HTTP请求

{raw_request}

# ==========================="""
        
        # 然后生成可执行的CURL命令
        parts = method_line.split(' ')
        if len(parts) < 2:
            return f"{original_request_section}\n\n# 无效的请求格式: {method_line}"
        
        method = parts[0]
        url = parts[1]
        
        # 处理CONNECT方法 - 转换为普通的HTTPS请求
        if method.upper() == 'CONNECT':
            # CONNECT host:port -> https://host/
            if url.endswith(':443'):
                # HTTPS端口，构建HTTPS URL
                host = url[:-4]  # 移除':443'
                url = f"https://{host}/"
                method = 'GET'  # 默认使用GET
            elif url.endswith(':80'):
                # HTTP端口，构建HTTP URL  
                host = url[:-3]  # 移除':80'
                url = f"http://{host}/"
                method = 'GET'
            else:
                # 其他端口，假设是HTTPS并保留端口
                if ':' in url:
                    url = f"https://{url}/"
                else:
                    url = f"https://{url}/"
                method = 'GET'
        
        # 开始构建CURL命令
        curl_parts = ['curl']
        
        # 添加方法（如果不是GET）
        if method.upper() != 'GET':
            curl_parts.extend(['-X', method.upper()])
        
        # 添加URL（用引号包围）
        curl_parts.append(f'"{url}"')
        
        # 添加请求头
        for key, value in headers.items():
            # 跳过一些自动生成或不需要的头
            if key.lower() in ['content-length', 'connection', 'proxy-connection']:
                continue
            curl_parts.extend(['-H', f'"{key}: {value}"'])
        
        # 添加请求体（如果有）
        if body and body.strip():
            curl_parts.extend(['-d', f"'{body}'"])
        
        # 添加常用选项
        curl_parts.extend([
            '--compressed',         # 支持压缩
            '--location',          # 跟随重定向  
            '--max-time', '30',    # 30秒超时
            '--connect-timeout', '10',  # 连接超时
            '--silent',            # 静默模式，不显示进度
            '--show-error'         # 但显示错误
        ])
        
        # 如果是HTTPS，添加SSL选项（针对测试环境）
        if url.startswith('https://'):
            curl_parts.extend([
                '--insecure',      # 忽略SSL证书验证（测试用）
                '--tlsv1.2'        # 使用TLS 1.2+
            ])
        
        # 先生成基础命令
        basic_curl = curl_parts.copy()
        
        # 为测试添加一些输出选项
        curl_parts.extend([
            '--verbose',           # 显示详细信息
            '--write-out', '"\\n\\nHTTP Status: %{http_code}\\nTotal Time: %{time_total}s\\nSize: %{size_download} bytes\\n"'
        ])
        
        # 生成两个版本的命令
        basic_command = self.format_curl_command(basic_curl, "等价CURL命令（基础版本）")
        verbose_command = self.format_curl_command(curl_parts, "等价CURL命令（详细版本，包含调试信息）")
        
        return f"""{original_request_section}

# ===== 等价CURL命令 =====
# 注意：CONNECT请求已转换为对应的HTTPS/HTTP请求
# 时间: {req.get('timestamp', '')}

{basic_command}

{verbose_command}"""
    
    def format_curl_command(self, curl_parts, title):
        """格式化CURL命令为多行"""
        result = f"# {title}\n"
        
        if len(curl_parts) > 6:  # 多行格式
            lines = []
            current_line = curl_parts[0]  # 开始with 'curl'
            
            for part in curl_parts[1:]:
                if part.startswith('-'):  # 新的选项
                    if len(current_line) > 70:  # 当前行太长，换行
                        lines.append(current_line + ' \\')
                        current_line = '  ' + part
                    else:
                        current_line += ' ' + part
                else:  # 选项的值
                    current_line += ' ' + part
            
            lines.append(current_line)  # 添加最后一行
            result += '\n'.join(lines)
        else:
            result += ' '.join(curl_parts)
        
        return result
    
    def serve_copy_page(self, query_params):
        """复制页面 - 显示请求的详细内容"""
        try:
            req_id = int(query_params.get('id', ['0'])[0])
            requests = list(reversed(self.proxy.requests_log[-50:]))
            
            if req_id >= len(requests):
                self.send_error(404, "请求不存在")
                return
                
            req = requests[req_id]
            
            # 构建完整CURL命令
            curl_command = self.build_curl_command(req)
            request_text = curl_command
            
            html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>复制请求 - IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .container {{ max-width: 800px; margin: 0 auto; }}
        .header {{ background: #17a2b8; color: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .content {{ background: white; padding: 20px; border-radius: 8px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin: 5px; }}
        .btn:hover {{ background: #5a67d8; }}
        textarea {{ width: 100%; height: 400px; font-family: monospace; font-size: 11px; line-height: 1.4; }}
        .info {{ background: #d4edda; padding: 15px; border-radius: 4px; margin: 10px 0; }}
    </style>
    <script>
        function copyToClipboard() {{
            const textarea = document.getElementById('requestText');
            textarea.select();
            document.execCommand('copy');
            alert('CURL命令已复制到剪贴板！可在终端中直接执行');
        }}
    </script>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>📋 复制CURL命令</h1>
            <p>完整的CURL命令，可直接在终端中执行</p>
        </div>
        
        <div class="content">
            <div class="info">
                <strong>时间：</strong>{html.escape(req.get('timestamp', ''))}<br>
                <strong>客户端：</strong>{html.escape(req.get('client_addr', ''))}<br>
                <strong>方法：</strong>{html.escape(req.get('method_line', ''))}
            </div>
            
            <h3>完整CURL命令：</h3>
            <textarea id="requestText" readonly>{html.escape(request_text)}</textarea>
            
            <div style="margin-top: 15px;">
                <button class="btn" onclick="copyToClipboard()">📋 复制CURL命令</button>
                <button class="btn" onclick="history.back()">↩️ 返回</button>
                <div style="margin-top: 10px; font-size: 12px; color: #666;">
                    💡 提示：复制后可直接在终端中执行此CURL命令
                </div>
            </div>
        </div>
    </div>
</body>
</html>"""
            
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            self.wfile.write(html_content.encode('utf-8'))
            
        except Exception as e:
            self.send_error(500, f"处理请求时出错: {str(e)}")

    def serve_replay_page(self, query_params):
        """重放页面 - 显示重放表单"""
        try:
            req_id = int(query_params.get('id', ['0'])[0])
            requests = list(reversed(self.proxy.requests_log[-50:]))
            
            if req_id >= len(requests):
                self.send_error(404, "请求不存在")
                return
                
            req = requests[req_id]
            
            html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>重放请求 - IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .container {{ max-width: 800px; margin: 0 auto; }}
        .header {{ background: #ffc107; color: #212529; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .content {{ background: white; padding: 20px; border-radius: 8px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin: 5px; }}
        .btn:hover {{ background: #5a67d8; }}
        .btn-danger {{ background: #dc3545; }}
        .btn-danger:hover {{ background: #c82333; }}
        .info {{ background: #fff3cd; padding: 15px; border-radius: 4px; margin: 10px 0; }}
        pre {{ background: #f8f9fa; padding: 10px; border-radius: 4px; overflow-x: auto; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔄 重放请求</h1>
            <p>重新发送HTTP请求</p>
        </div>
        
        <div class="content">
            <div class="info">
                <strong>⚠️ 注意：</strong>重放请求将会向目标服务器发送真实的HTTP请求！<br>
                <strong>📡 网络状态：</strong>{self.get_network_info()}<br>
                <strong>💡 如果重放失败，建议使用"复制"功能获取CURL命令进行测试</strong>
            </div>
            
            <h3>请求详情：</h3>
            <pre>{html.escape(req.get('method_line', ''))}
{html.escape(str(req.get('headers', {})))}</pre>
            
            <form method="post" action="/replay_request">
                <input type="hidden" name="req_id" value="{req_id}">
                <button type="submit" class="btn btn-danger">🚀 确认重放请求</button>
                <button type="button" class="btn" onclick="history.back()">↩️ 取消</button>
            </form>
        </div>
    </div>
</body>
</html>"""
            
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            self.wfile.write(html_content.encode('utf-8'))
            
        except Exception as e:
            self.send_error(500, f"处理请求时出错: {str(e)}")

    def handle_replay_post(self, post_params):
        """处理重放请求"""
        try:
            req_id = int(post_params.get('req_id', ['0'])[0])
            requests = list(reversed(self.proxy.requests_log[-50:]))
            
            if req_id >= len(requests):
                self.send_error(404, "请求不存在")
                return
                
            req = requests[req_id]
            method_line = req.get('method_line', '')
            headers = req.get('headers', {})
            
            # 执行重放
            result = self.replay_request(method_line, headers)
            
            html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>重放结果 - IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .container {{ max-width: 800px; margin: 0 auto; }}
        .header {{ background: #28a745; color: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .content {{ background: white; padding: 20px; border-radius: 8px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin: 5px; }}
        .btn:hover {{ background: #5a67d8; }}
        .result {{ background: #f8f9fa; padding: 15px; border-radius: 4px; margin: 10px 0; max-height: 400px; overflow-y: auto; }}
        .error {{ background: #f8d7da; color: #721c24; }}
        .success {{ background: #d4edda; color: #155724; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>✅ 重放完成</h1>
            <p>请求重放结果</p>
        </div>
        
        <div class="content">
            <h3>原始请求：</h3>
            <div class="result">{html.escape(method_line)}</div>
            
            <h3>重放结果：</h3>
            <div class="result {'success' if result.get('success') else 'error'}">
                <pre>{html.escape(result.get('response', result.get('error', '未知错误')))}</pre>
            </div>
            
            <button class="btn" onclick="history.back()">↩️ 返回</button>
            <button class="btn" onclick="location.href='/'">🏠 首页</button>
        </div>
    </div>
</body>
</html>"""
            
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            self.wfile.write(html_content.encode('utf-8'))
            
        except Exception as e:
            self.send_error(500, f"重放请求时出错: {str(e)}")

    def serve_network_test_page(self):
        """网络测试页面"""
        # 测试常见网站的连接
        test_sites = [
            ('百度', 'www.baidu.com', 443),
            ('Google', 'www.google.com', 443),
            ('JetBrains插件', 'plugins.jetbrains.com', 443),
            ('Maven中央仓库', 'repo1.maven.org', 80),
            ('GitHub', 'github.com', 443)
        ]
        
        test_results = []
        for name, host, port in test_sites:
            result = self.test_connection(host, port)
            test_results.append({
                'name': name,
                'host': host,
                'port': port,
                'success': result['success'],
                'error': result.get('error', '')
            })
        
        html_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>网络连接测试 - IDEA Proxy Monitor</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }}
        .container {{ max-width: 800px; margin: 0 auto; }}
        .header {{ background: #28a745; color: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; }}
        .content {{ background: white; padding: 20px; border-radius: 8px; }}
        .btn {{ background: #667eea; color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; margin: 5px; }}
        .btn:hover {{ background: #5a67d8; }}
        .test-result {{ padding: 10px; margin: 10px 0; border-radius: 4px; }}
        .success {{ background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }}
        .failed {{ background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }}
        .network-info {{ background: #d1ecf1; padding: 15px; border-radius: 4px; margin: 20px 0; }}
        table {{ width: 100%; border-collapse: collapse; margin-top: 20px; }}
        th, td {{ padding: 12px; text-align: left; border-bottom: 1px solid #eee; }}
        th {{ background: #f8f9fa; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🌐 网络连接测试</h1>
            <p>检测网络连接状态，帮助诊断重放功能问题</p>
        </div>
        
        <div class="content">
            <div class="network-info">
                <strong>🔍 网络信息：</strong>{self.get_network_info()}<br>
                <strong>💡 说明：</strong>如果多个网站连接失败，可能是网络配置问题
            </div>
            
            <h3>连接测试结果：</h3>
            <table>
                <thead>
                    <tr>
                        <th>网站</th>
                        <th>地址</th>
                        <th>端口</th>
                        <th>状态</th>
                        <th>说明</th>
                    </tr>
                </thead>
                <tbody>
"""
        
        for result in test_results:
            status_class = 'success' if result['success'] else 'failed'
            status_text = '✅ 连接成功' if result['success'] else f"❌ 连接失败"
            error_text = '' if result['success'] else result['error']
            
            html_content += f"""
                    <tr class="{status_class}">
                        <td>{html.escape(result['name'])}</td>
                        <td>{html.escape(result['host'])}</td>
                        <td>{result['port']}</td>
                        <td>{status_text}</td>
                        <td>{html.escape(error_text)}</td>
                    </tr>
            """
        
        html_content += """
                </tbody>
            </table>
            
            <div style="margin-top: 20px;">
                <h3>🔧 故障排除建议：</h3>
                <ul>
                    <li><strong>所有连接都失败：</strong>检查网络连接或防火墙设置</li>
                    <li><strong>HTTPS连接失败：</strong>可能是SSL/TLS配置问题</li>
                    <li><strong>特定网站失败：</strong>目标服务器可能不可达或阻止连接</li>
                    <li><strong>间歇性失败：</strong>网络不稳定，建议使用CURL命令测试</li>
                </ul>
                
                <div style="margin-top: 20px;">
                    <button class="btn" onclick="location.reload()">🔄 重新测试</button>
                    <button class="btn" onclick="location.href='/'">🏠 返回首页</button>
                </div>
            </div>
        </div>
    </div>
</body>
</html>"""
        
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(html_content.encode('utf-8'))

    def replay_request(self, method_line, headers):
        """重放HTTP请求 - 改进的错误处理"""
        try:
            parts = method_line.split(' ')
            if len(parts) < 2:
                return {'success': False, 'error': '无效的请求格式'}
            
            method = parts[0]
            url = parts[1]
            parsed_url = urlparse(url)
            
            host = parsed_url.netloc
            if ':' in host:
                host, port = host.split(':')
                port = int(port)
            else:
                port = 443 if parsed_url.scheme == 'https' else 80
            
            # 网络连接检测
            connection_test = self.test_connection(host, port)
            if not connection_test['success']:
                return {
                    'success': False, 
                    'error': f"网络连接失败: {connection_test['error']}\\n\\n建议:\\n1. 检查网络连接\\n2. 确认目标服务器可访问\\n3. 使用CURL命令代替重放功能"
                }
            
            # 构建HTTP请求
            crlf = '\\r\\n'
            request_data = method_line + crlf
            for key, value in headers.items():
                # 过滤一些可能导致问题的头
                if key.lower() in ['proxy-connection', 'proxy-authorization']:
                    continue
                request_data += f"{key}: {value}{crlf}"
            request_data += crlf
            
            # 发送请求
            response_data = self.send_http_request(parsed_url.scheme, host, port, request_data)
            
            if response_data['success']:
                return {
                    'success': True,
                    'response': response_data['data'][:3000]  # 增加响应长度
                }
            else:
                return {
                    'success': False,
                    'error': f"请求发送失败: {response_data['error']}"
                }
            
        except Exception as e:
            return {
                'success': False, 
                'error': f"重放请求异常: {str(e)}\\n\\n这通常是由于:\\n1. 目标服务器不可达\\n2. 网络配置问题\\n3. SSL证书问题\\n\\n建议使用复制的CURL命令进行测试"
            }
    
    def test_connection(self, host, port):
        """测试网络连接"""
        try:
            # 简单的TCP连接测试
            test_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            test_sock.settimeout(5)  # 5秒超时
            result = test_sock.connect_ex((host, port))
            test_sock.close()
            
            if result == 0:
                return {'success': True}
            else:
                return {'success': False, 'error': f"无法连接到 {host}:{port} (错误代码: {result})"}
                
        except socket.gaierror as e:
            return {'success': False, 'error': f"DNS解析失败: {host} - {str(e)}"}
        except Exception as e:
            return {'success': False, 'error': f"连接测试失败: {str(e)}"}
    
    def send_http_request(self, scheme, host, port, request_data):
        """发送HTTP请求"""
        try:
            if scheme == 'https':
                return self.send_https_request(host, port, request_data)
            else:
                return self.send_http_request_plain(host, port, request_data)
        except Exception as e:
            return {'success': False, 'error': str(e)}
    
    def send_https_request(self, host, port, request_data):
        """发送HTTPS请求"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(15)  # 增加超时时间
            
            context = ssl.create_default_context()
            context.check_hostname = False
            context.verify_mode = ssl.CERT_NONE
            
            ssl_sock = context.wrap_socket(sock, server_hostname=host)
            ssl_sock.connect((host, port))
            ssl_sock.send(request_data.encode('utf-8'))
            
            response = b''
            start_time = time.time()
            while True:
                try:
                    if time.time() - start_time > 10:  # 10秒读取超时
                        break
                    data = ssl_sock.recv(4096)
                    if not data:
                        break
                    response += data
                    if len(response) > 50000:  # 增加响应大小限制
                        response += '\\n\\n[响应过长，已截断...]'.encode('utf-8')
                        break
                except socket.timeout:
                    break
            
            ssl_sock.close()
            
            return {
                'success': True,
                'data': response.decode('utf-8', errors='ignore')
            }
            
        except ssl.SSLError as e:
            return {'success': False, 'error': f"SSL错误: {str(e)}"}
        except socket.timeout:
            return {'success': False, 'error': "请求超时"}
        except Exception as e:
            return {'success': False, 'error': f"HTTPS请求错误: {str(e)}"}
    
    def send_http_request_plain(self, host, port, request_data):
        """发送HTTP请求"""
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(15)
            sock.connect((host, port))
            sock.send(request_data.encode('utf-8'))
            
            response = b''
            start_time = time.time()
            while True:
                try:
                    if time.time() - start_time > 10:
                        break
                    data = sock.recv(4096)
                    if not data:
                        break
                    response += data
                    if len(response) > 50000:
                        response += '\\n\\n[响应过长，已截断...]'.encode('utf-8')
                        break
                except socket.timeout:
                    break
            
            sock.close()
            
            return {
                'success': True,
                'data': response.decode('utf-8', errors='ignore')
            }
            
        except socket.timeout:
            return {'success': False, 'error': "请求超时"}
        except Exception as e:
            return {'success': False, 'error': f"HTTP请求错误: {str(e)}"}
    
    def get_network_info(self):
        """获取网络信息用于调试"""
        try:
            import subprocess
            result = subprocess.run(['hostname', '-I'], capture_output=True, text=True, timeout=3)
            local_ip = result.stdout.strip().split()[0] if result.stdout.strip() else "unknown"
            return f"本地IP: {local_ip}"
        except:
            return "无法获取网络信息"

    def log_message(self, format, *args):
        # 禁用HTTP服务器日志
        pass


class SimpleDashboard:
    def __init__(self, proxy_instance, port=8081):
        self.proxy = proxy_instance
        self.port = port
        self.server = None
        self.thread = None

    def start(self):
        """启动dashboard服务器"""
        def handler(*args, **kwargs):
            return SimpleDashboardHandler(self.proxy, *args, **kwargs)
        
        self.server = HTTPServer(('0.0.0.0', self.port), handler)
        self.thread = threading.Thread(target=self.server.serve_forever)
        self.thread.daemon = True
        self.thread.start()
        
        # 获取WSL IP地址
        try:
            result = subprocess.run(['hostname', '-I'], capture_output=True, text=True, timeout=5)
            wsl_ip = result.stdout.strip().split()[0] if result.stdout.strip() else "localhost"
            print(f"🌐 Simple Dashboard started:")
            print(f"   WSL访问: http://localhost:{self.port}")
            print(f"   Windows访问: http://{wsl_ip}:{self.port}")
        except:
            print(f"🌐 Simple Dashboard started at http://0.0.0.0:{self.port}")

    def stop(self):
        """停止dashboard服务器"""
        if self.server:
            self.server.shutdown()
            self.server.server_close()
        if self.thread:
            self.thread.join()


if __name__ == '__main__':
    # 测试用例
    class MockProxy:
        def __init__(self):
            from datetime import datetime
            self.requests_log = [
                {
                    'timestamp': datetime.now().isoformat(),
                    'client_addr': '127.0.0.1:12345',
                    'method_line': 'GET https://plugins.jetbrains.com/api/plugins HTTP/1.1',
                    'headers': {
                        'User-Agent': 'IntelliJ IDEA/2023.3',
                        'Host': 'plugins.jetbrains.com'
                    }
                }
            ]
    
    mock_proxy = MockProxy()
    dashboard = SimpleDashboard(mock_proxy)
    dashboard.start()
    
    try:
        print("Simple Dashboard running... Press Ctrl+C to stop")
        import time
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        dashboard.stop()
        print("Dashboard stopped")